package dk.eclipse.android.badassapp.sms;

import java.util.HashMap;

import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemSelectedListener;
import dk.eclipse.android.badassapp.R;
import dk.eclipse.android.badassapp.contact.ContactArrayAdapter;
import dk.eclipse.android.badassapp.contact.ContactInfo;
import dk.eclipse.android.badassapp.contact.ContactsHelper;
import dk.eclipse.android.badassapp.helper.SMSHelper;

/**
 * This class prensents a user interface for sending quick SMS commands.
 * 
 * @author Ronni Kahalani (eclipse.dk)
 * 
 */
public class SMSCommandoActivity extends ListActivity {
	/**
	 * Shown in every log line as identification.
	 */
	private static final String LOG_TAG = SMSCommandoActivity.class
			.getSimpleName();
	/**
	 * Holds the current selected contact display name.
	 */
	private TextView contactNameText;
	/**
	 * Holds the current selected contact phone number.
	 */
	private TextView contactPhoneNumberText;
	/**
	 * Holds the current selected contact photo.
	 */
	private ImageView contactPhoto;
	/**
	 * Holds the actual message to send.
	 */
	private EditText msgText;
	/**
	 * A simple progress indicator, which is active when sending an SMS.
	 */
	private ProgressBar progressBar;
	/**
	 * Handles the contact list.
	 */
	private ListAdapter contactListAdapter;
	/**
	 * Used to decide if a delivery report is requested.
	 */
	private CheckBox deliveryReportCheckBox;
	/**
	 * Caches all the used contacts.
	 */
	private HashMap<Long, ContactInfo> contactCache = new HashMap<Long, ContactInfo>();

	protected static final int CONTEXTMENU_VIEW_CONTACT = 0;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		requestWindowFeature(Window.FEATURE_LEFT_ICON);
		setContentView(R.layout.sms);
		setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_app);
		
		registerForContextMenu(getListView());
		
		createMessageSpinner();
		createContactList();
		createBottomArea();
	}

	/**
	 * Creates the bottom area on the screen.
	 */
	private void createBottomArea() {
		contactPhoto = (ImageView) findViewById(R.id.contactPhoto);
		contactNameText = (TextView) findViewById(R.id.contact_name_text);
		contactPhoneNumberText = (TextView) findViewById(R.id.contact_phonenumber_text);
		msgText = (EditText) findViewById(R.id.contactMsgEdit);

		deliveryReportCheckBox = (CheckBox) findViewById(R.id.DeliveryReportCheckBox);
		progressBar = (ProgressBar) findViewById(R.id.smsProgressBar);

		Button sendButton = (Button) findViewById(R.id.sendButton);
		sendButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				SMSHelper.sendSMS(getApplicationContext(),
						contactPhoneNumberText.getText().toString(), msgText
								.getText().toString(), deliveryReportCheckBox
								.isChecked(), progressBar, R.drawable.sms_sent, R.drawable.sms_delivered);
			}
		});
	}

	/**
	 * Creates the message spinner control.
	 */
	private void createMessageSpinner() {
		// Get the common message spinner / dropdown / combo.
		Spinner msgSpinner = (Spinner) findViewById(R.id.msgSpinner);
		// Add a listener
		msgSpinner
				.setOnItemSelectedListener(new MessageSpinnerOnItemSelectedListener());
		// Create a array adapter for the spinner, and use the msgs string
		// resource.
		ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(this,
				R.array.msgs, android.R.layout.simple_spinner_item);
		// Set the adapter to use the simple spinner dropdown item resource.
		adapter
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		// Set the common message spinner adapter to the newly configured
		// adapter.
		msgSpinner.setAdapter(adapter);
	}

	/**
	 * Retrieves and lists all contacts that has a phone number.
	 */
	private void createContactList() {

		// Find all contacts with a phone number.
		Cursor cur = findContactsWithPhoneNumber();
		startManagingCursor(cur);

		String[] columns = { ContactsContract.Contacts.DISPLAY_NAME };
		int[] names = { R.id.nameText };

		contactListAdapter = new ContactArrayAdapter(this, R.layout.target_row_layout,
				cur, columns, names);

		setListAdapter(contactListAdapter);
		getListView().setTextFilterEnabled(true);

	}

	/**
	 * Builds a query that retrieves every contact with at least 1 phone number.
	 * 
	 * @return a Cursor referencing all contacts with at least 1 phone number.
	 */
	private Cursor findContactsWithPhoneNumber() {
		String[] projection = new String[] { ContactsContract.Contacts._ID,
				ContactsContract.Contacts.DISPLAY_NAME,
				ContactsContract.Contacts.HAS_PHONE_NUMBER };

		String query = ContactsContract.Contacts.HAS_PHONE_NUMBER + ">?";
		String[] queryArgs = new String[] { "0" };
		String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " ASC";

		Cursor cursor = managedQuery(Contacts.CONTENT_URI, projection, query,
				queryArgs, sortOrder);
		return cursor;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.ListActivity#onListItemClick(android.widget.ListView,
	 * android.view.View, int, long)
	 */
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);

		Cursor cursor = (Cursor) contactListAdapter.getItem(position);
		Long contactId = cursor.getLong(cursor
				.getColumnIndex(ContactsContract.Contacts._ID));

		ContactInfo info = null;
		if (contactCache.containsKey(contactId)) {
			info = contactCache.get(contactId);

		} else {

			final Cursor contacts = ContactsHelper.getContactCursor(this,
					contactId);

			try {
				if (contacts.moveToFirst()) {

					info = new ContactInfo(contactId, ContactsHelper
							.getContactDisplayName(contacts), ContactsHelper
							.getContactPhoneNumber(contacts), ContactsHelper
							.getPhoto(getContentResolver(), contactId));
					contactCache.put(contactId, info);
				}
			} catch (Exception e) {
				Log.d(LOG_TAG, e.getMessage());
			} finally {
				contacts.close();
			}
		}

		contactPhoto.setImageBitmap(info.getPhoto());
		contactPhoneNumberText.setText(info.getPhoneNumber());
		contactNameText.setText(info.getDisplayName());
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.context_menu, menu);
		menu.setHeaderTitle("Contact Options");
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		// Here's how you can get the correct item in onContextItemSelected()
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
				.getMenuInfo();

		// Get the Adapter behind your ListView (this assumes you're using
		// a ListActivity; if you're not, you'll have to store the Adapter
		// yourself
		// in some way that can be accessed here.)
		Adapter adapter = getListAdapter();

		// Retrieve the item that was clicked on
		Long contactId = ContactsHelper.getContactId((Cursor) adapter
				.getItem(info.position));

		Intent intent = null;
		String action = null;
		Uri uri = null;

		int itemId = item.getItemId();

		switch (itemId) {
		case R.id.viewTargetMenuItem:
			action = Intent.ACTION_VIEW;
			uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI,
					contactId.toString());
			break;

		case R.id.callTargetMenuItem:

			Cursor contact = ContactsHelper.getContactCursor(
					SMSCommandoActivity.this, contactId);
			String phoneNumber = null;
			try {
				if (contact.moveToFirst()) {
					phoneNumber = ContactsHelper.getContactPhoneNumber(contact);
					action = Intent.ACTION_CALL;
					uri = Uri.parse("tel:" + phoneNumber);

				}
			} catch (Exception e) {
				Log.d(LOG_TAG, e.getMessage());
			} finally {
				contact.close();
			}

			break;
		default:
			break;
		}

		if (action != null) {
			intent = new Intent(action, uri);
			startActivity(intent);
			return true;
		}
		return false;
	}

	/**
	 * This selection listener is used to handle selections from the common
	 * message dropdown / spinner.
	 * 
	 * @author Ronni Kahalani (eclipse.dk)
	 * 
	 */
	public class MessageSpinnerOnItemSelectedListener implements
			OnItemSelectedListener {

		public void onItemSelected(AdapterView<?> parent, View view, int pos,
				long id) {

			String msg = parent.getItemAtPosition(pos).toString();
			msgText.setText(msg);
		}

		@SuppressWarnings("unchecked")
		public void onNothingSelected(AdapterView parent) {
			// Do nothing.
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.ListActivity#onDestroy()
	 */
	@Override
	protected void onDestroy() {
		if (contactCache != null) {
			contactCache.clear();
		}
		super.onDestroy();
	}

}